//*****************************************************************************
// JFab (http://code.google.com/p/jfab)
// Copyright (c) 2011-2012 JFab.org
// Admin jfab@jeffreythompson.net
//
// See the file "LICENSE.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//*****************************************************************************

package org.jfab.swingui.decorator;

import javax.swing.Icon;

import org.apache.commons.lang3.StringUtils;
import org.jfab.core.model.CGClass;
import org.jfab.core.model.CGConstructor;
import org.jfab.core.model.CGField;
import org.jfab.core.model.CGInitializationBlock;
import org.jfab.core.model.CGMethod;
import org.jfab.core.model.CGObject;
import org.jfab.core.model.CGSpec;
import org.jfab.swingui.IconManager;
import org.jfab.swingui.editpane.CGClassEditPane;
import org.jfab.swingui.editpane.EditPane;

/**
 * Provides a decorator implementation for <code>CGClass</code>.
 * <p>
 * Possible children are:
 * <ul>
 * <li>initialization block</li>
 * <li>field</li>
 * <li>constructor</li>
 * <li>method</li>
 * </ul>
 * </p>
 */
public class CGClassDecorator extends CGConcreteUnitDecorator<CGClass>
{
    /** Child selection values. */
    private static final String[] CHILD_SELECTION_VALUES = {
            "initializationBlock", "field", "constructor", "method", };

    /**
     * Construct this object with the given parameter.
     * 
     * @param component Component.
     * @param parent Parent.
     * @param iconManager Icon manager.
     */
    public CGClassDecorator(final CGClass component, final Decorator<?> parent,
            final IconManager iconManager)
    {
        super(component, parent, iconManager);
    }

    @Override
    public void addNode(final String childTypeName)
    {
        if (StringUtils.isNotEmpty(childTypeName))
        {
            final CGClass parent = getComponent();
            final CGObject newChild = getModelFactory().create(childTypeName);

            if (newChild instanceof CGInitializationBlock)
            {
                parent.getInitializationBlocks().add(
                        (CGInitializationBlock)newChild);
            }
            else if (newChild instanceof CGField)
            {
                parent.getFields().add((CGField)newChild);
            }
            else if (newChild instanceof CGConstructor)
            {
                parent.getConstructors().add((CGConstructor)newChild);
            }
            else if (newChild instanceof CGMethod)
            {
                parent.getMethods().add((CGMethod)newChild);
            }
        }
    }

    @Override
    public Object getChild(final int index)
    {
        Object answer;

        final CGClass cgClass = getComponent();

        int baseIndex = 0;

        if (index < (baseIndex + cgClass.getInitializationBlocks().size()))
        {
            answer = cgClass.getInitializationBlocks().get(index - baseIndex);
        }
        else
        {
            baseIndex = cgClass.getInitializationBlocks().size();

            if (index < (baseIndex + cgClass.getFields().size()))
            {
                answer = cgClass.getFields().get(index - baseIndex);
            }
            else
            {
                baseIndex += cgClass.getFields().size();

                if (index < (baseIndex + cgClass.getConstructors().size()))
                {
                    answer = cgClass.getConstructors().get(index - baseIndex);
                }
                else
                {
                    baseIndex += cgClass.getConstructors().size();
                    answer = cgClass.getMethods().get(index - baseIndex);
                }
            }
        }

        return answer;
    }

    @Override
    public int getChildCount()
    {
        final CGClass cgClass = getComponent();

        return cgClass.getInitializationBlocks().size()
                + cgClass.getConstructors().size() + cgClass.getFields().size()
                + cgClass.getMethods().size();
    }

    @Override
    public String[] getChildSelectionValues()
    {
        return CHILD_SELECTION_VALUES;
    }

    @Override
    public EditPane<CGClass> getEditPane()
    {
        return new CGClassEditPane(getComponent());
    }

    @Override
    public Icon getIcon()
    {
        return getIconManager().getClassIcon();
    }

    @Override
    public int getIndexOfChild(final Object child)
    {
        int answer = -1;

        final CGClass cgClass = getComponent();

        if (child instanceof CGInitializationBlock)
        {
            final int index = cgClass.getInitializationBlocks().indexOf(child);

            if (index >= 0)
            {
                answer = index;
            }
        }
        else if (child instanceof CGField)
        {
            final int index = cgClass.getFields().indexOf(child);

            if (index >= 0)
            {
                answer = index;
            }
        }
        else if (child instanceof CGConstructor)
        {
            final int index = cgClass.getConstructors().indexOf(child);

            if (index >= 0)
            {
                answer = cgClass.getFields().size() + index;
            }
        }
        else if (child instanceof CGMethod)
        {
            final int index = cgClass.getMethods().indexOf(child);

            if (index >= 0)
            {
                answer = cgClass.getFields().size()
                        + cgClass.getConstructors().size() + index;
            }
        }

        return answer;
    }

    @Override
    public boolean isLeaf()
    {
        final CGClass cgClass = getComponent();

        return cgClass.getInitializationBlocks().isEmpty()
                && cgClass.getConstructors().isEmpty()
                && cgClass.getFields().isEmpty()
                && cgClass.getMethods().isEmpty();
    }

    @Override
    public boolean removeNode()
    {
        final CGSpecDecorator parent = (CGSpecDecorator)getParent();
        final CGSpec cgSpec = parent.getComponent();

        return cgSpec.getClasses().remove(this.getComponent());
    }
}
